import 'dart:ui' as ui;

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_shader/generated/assets.dart';
import 'package:flutter_shader/widgets/shadertoy.dart';

const _imageKeys = [
  Images.test0,
  Images.test1,
  Images.test2,
  Images.test3,
  Images.test4,
  Images.test5,
  Images.test6,
  Images.test7,
];

/// Created by changlei on 2024/2/22.
///
/// 图片
class ImagePage extends StatefulWidget {
  /// 图片
  const ImagePage({super.key});

  @override
  State<ImagePage> createState() => _ImagePageState();
}

class _ImagePageState extends State<ImagePage> {
  final _images = <ui.Image>[];

  @override
  void initState() {
    super.initState();
    Future.wait(_imageKeys.map(Assets.images).map(loadImage)).then((value) {
      if (mounted) {
        setState(() {
          _images.clear();
          _images.addAll(value);
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(),
      child: ShaderBuilder(
        assetKey: Assets.shaders(Shaders.image),
        builder: (context, shader, child) {
          if (shader == null || _images.isEmpty) {
            child = const Center(
              child: CupertinoActivityIndicator(
                radius: 24,
              ),
            );
          } else {
            child = ListView.builder(
              itemCount: _images.length,
              itemBuilder: (context, index) {
                return KeyedSubtree(
                  key: ValueKey(_images[index]),
                  child: Card(
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10),
                    ),
                    clipBehavior: Clip.hardEdge,
                    child: FittedBox(
                      fit: BoxFit.contain,
                      alignment: Alignment.center,
                      child: _ShaderPaint(
                        shader: shader,
                        image: _images[index],
                      ),
                    ),
                  ),
                );
              },
            );
          }
          return child;
        },
      ),
    );
  }
}

class _ShaderPaint extends StatelessWidget {
  const _ShaderPaint({
    Key? key,
    required this.shader,
    required this.image,
  }) : super(key: key);

  final ui.FragmentShader shader;
  final ui.Image image;

  @override
  Widget build(BuildContext context) {
    final pixelRatio = MediaQuery.devicePixelRatioOf(context);
    return CustomPaint(
      size: Size(
        image.width / pixelRatio,
        image.height / pixelRatio,
      ),
      painter: _ShaderPainter(
        shader: shader,
        image: image,
      ),
    );
  }
}

final class _ShaderPainter extends CustomPainter {
  const _ShaderPainter({
    required this.shader,
    required this.image,
  });

  final ui.FragmentShader shader;
  final ui.Image image;

  @override
  void paint(Canvas canvas, Size size) {
    shader.setFloat(0, size.width);
    shader.setFloat(1, size.height);
    shader.setImageSampler(0, image);
    final paint = Paint()..shader = shader;
    canvas.drawRect(Offset.zero & size, paint);
  }

  @override
  bool shouldRepaint(covariant _ShaderPainter oldDelegate) {
    return oldDelegate.shader != shader || oldDelegate.image != image;
  }
}
